import frappe
from frappe.desk.search import search_link as original_search_link
from link_history.utils.link_history import get_link_history, is_link_history_disabled, get_link_history_limit
from datetime import datetime
from frappe.utils.data import pretty_date
import json

def format_date(date_str):
    """格式化日期字符串为友好的相对时间"""
    if not date_str:
        return frappe._("Recently")
    
    try:
        # 如果是字符串，尝试解析为日期时间
        if isinstance(date_str, str):
            try:
                # 尝试直接使用 pretty_date
                return pretty_date(date_str)
            except:
                # 如果失败，尝试手动解析日期
                try:
                    # 尝试解析 ISO 格式的日期时间
                    date = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
                    return pretty_date(date)
                except ValueError:
                    # 尝试解析其他常见格式
                    formats = [
                        '%Y-%m-%d %H:%M:%S',
                        '%Y-%m-%d %H:%M:%S.%f',
                        '%Y-%m-%d'
                    ]
                    for fmt in formats:
                        try:
                            date = datetime.strptime(date_str, fmt)
                            return pretty_date(date)
                        except ValueError:
                            continue
        
        # 如果是日期对象，直接使用
        return pretty_date(date_str)
    except Exception as e:
        frappe.log_error(f"格式化日期时出错: {e}", "Link History")
        return frappe._("Recently")


@frappe.whitelist()
def patched_search_link(
    doctype, txt, query=None, filters=None, page_length=10, searchfield=None, reference_doctype=None, ignore_user_permissions=False
):
    """添加历史记录到搜索结果中"""
    # 获取原始搜索结果
    original_results = original_search_link(
        doctype, txt, query, filters, page_length, searchfield, reference_doctype, ignore_user_permissions
    )
    
    # 检查是否禁用
    if is_link_history_disabled():
        return original_results
    
    try:
        # 获取历史记录显示条数限制
        history_limit = get_link_history_limit()
        
        # 获取历史记录 - 增加限制以便有更多记录可以过滤
        history = get_link_history(doctype, reference_doctype, limit=20)
        
        # 如果没有历史记录，直接返回原始结果
        if not history:
            return original_results
        
        # 收集所有历史记录的名称
        history_names = [item.get("link_name") for item in history if item.get("link_name") and item.get("link_name") != "undefined"]
        
        # 如果没有有效的历史记录名称，直接返回原始结果
        if not history_names:
            return original_results
        
        # 一次性检查所有历史记录是否符合过滤条件
        valid_names = filter_allowed_docs_batch(doctype, history_names, filters)
        
        # 如果没有符合条件的历史记录，直接返回原始结果
        if not valid_names:
            return original_results
        
        # 创建一个名称到历史记录项的映射，方便后续查找
        name_to_history = {item.get("link_name"): item for item in history if item.get("link_name") in valid_names}
        
        # 检查文档类型是否显示标题
        show_title = frappe.get_cached_value('DocType', doctype, 'show_title_field_in_link') or False
        
        # 如果需要显示标题，一次性获取所有文档的标题
        name_to_title = {}
        if show_title:
            # 获取文档类型的标题字段
            title_field = frappe.get_cached_value('DocType', doctype, 'title_field')
            
            if title_field:
                # 如果有标题字段，一次性查询所有文档的标题
                titles = frappe.get_all(
                    doctype,
                    filters={"name": ["in", valid_names]},
                    fields=["name", title_field]
                )
                
                # 创建名称到标题的映射
                for doc in titles:
                    name_to_title[doc.name] = doc.get(title_field) or doc.name
            else:
                # 如果没有标题字段，检查是否有自定义的 get_title 方法
                # 为了性能考虑，可以先检查一个示例文档
                try_custom_title = False
                if valid_names:
                    try:
                        # 尝试获取一个示例文档
                        sample_doc = frappe.get_cached_doc(doctype, valid_names[0])
                        # 检查是否有自定义的 get_title 方法
                        if hasattr(sample_doc, 'get_title') and sample_doc.get_title() != valid_names[0]:
                            try_custom_title = True
                    except:
                        pass
                
                if try_custom_title:
                    # 只有在确认有自定义 get_title 方法时才加载所有文档
                    for name in valid_names:
                        try:
                            doc = frappe.get_cached_doc(doctype, name)
                            name_to_title[name] = doc.get_title()
                        except:
                            name_to_title[name] = name
                else:
                    # 如果没有自定义 get_title 方法，直接使用 name 作为标题
                    for name in valid_names:
                        name_to_title[name] = name
        
        # 创建历史记录项
        filtered_history_items = []
        
        # 处理符合条件的历史记录
        for name in valid_names:
            item = name_to_history.get(name)
            if not item:
                continue
            
            # 获取文档标题
            if show_title:
                # 从之前准备好的映射中获取标题
                doc_title = name_to_title.get(name)
                
                # 如果没有找到标题，尝试从历史记录中获取
                if not doc_title:
                    doc_title = item.get("link_title") or name
                
                if not doc_title or doc_title == "undefined":
                    doc_title = name
            else:
                # 如果不显示标题，直接使用 name
                doc_title = name
                
            frequency = int(item.get("frequency", 1))
            last_used = format_date(item.get("last_used"))
            
            # 创建历史记录项
            history_item = {
                "value": name,
                "label": doc_title,  # 根据设置使用适当的标题
                "description": f'{frappe._("Used Frequency")} {frequency} {frappe._("times")} - {frappe._("Last used")}: {last_used}'
            }
            
            # 如果搜索文本不为空，过滤历史记录
            if txt:
                txt_lower = txt.lower()
                if (txt_lower in name.lower() or 
                    txt_lower in doc_title.lower()):
                    filtered_history_items.append(history_item)
            else:
                # 如果搜索文本为空，添加所有历史记录
                filtered_history_items.append(history_item)
        
        # 如果有符合条件的历史记录
        if filtered_history_items:
            # 限制历史记录数量 - 使用设置中的限制
            filtered_history_items = filtered_history_items[:history_limit]
            
            # 创建最终结果
            result = []
            
            # 添加过滤后的历史记录
            result.extend(filtered_history_items)
            
            # 添加原始结果
            if original_results:
                result.extend(original_results)
            
            # 返回最终结果
            return result
    except Exception as e:
        # 记录错误但不中断流程
        frappe.log_error(f"获取历史记录时出错: {e}", "Link History")
    
    # 如果没有历史记录或出错，返回原始结果
    return original_results

def filter_allowed_docs_batch(doctype, names, filters):
    """一次性检查多个记录是否符合过滤条件"""
    if not names or not filters:
        return names
    
    try:
        # 构建查询条件
        combined_filters = []
        
        # 添加名称条件 - 使用 IN 操作符一次性查询所有名称
        combined_filters.append(["name", "in", names])
        
        # 添加原始过滤条件
        if isinstance(filters, str):
            try:
                filters = json.loads(filters)
            except:
                return []
        
        if isinstance(filters, dict):
            for field, value in filters.items():
                if isinstance(value, list) and len(value) >= 2:
                    # 已经是 [field, operator, value] 格式
                    combined_filters.append([field, value[0], value[1]])
                else:
                    # 转换为 [field, "=", value] 格式
                    combined_filters.append([field, "=", value])
        elif isinstance(filters, list):
            # 如果已经是列表格式，直接添加
            combined_filters.extend(filters)
        
        # 使用 frappe.get_list 一次性查询所有符合条件的记录
        results = frappe.get_list(
            doctype,
            filters=combined_filters,
            fields=["name"],
            limit_page_length=len(names)
        )
        
        # 提取名称
        return [r.name for r in results]
    except Exception as e:
        frappe.log_error(f"批量过滤历史记录时出错: {e}", "Link History")
        return []